import 'dart:async';
import 'dart:convert';
import 'dart:typed_data';
import 'package:avatar_glow/avatar_glow.dart';
import 'package:chatbot/page/provider_example.dart';
import 'package:flutter_native_splash/flutter_native_splash.dart';
import 'package:flutter_tts/flutter_tts.dart';
import 'package:in_app_review/in_app_review.dart';
import 'package:chatbot/manager/event_bus.dart';
import 'package:chatbot/manager/store_manager.dart';
import 'package:chatbot/model/Question.dart';
import 'package:chatbot/model/event.dart';
import 'package:chatbot/page/role_page.dart';
import 'package:chatbot/page/vip_page.dart';
import 'package:chatbot/sse/sse_event_model.dart';
import 'package:chatbot/utils/utils.dart';
import 'package:chatbot/widget/three_bounce.dart';
import 'package:flutter/cupertino.dart';
import 'package:speech_to_text/speech_recognition_result.dart';
import 'package:chatbot/utils/colors.dart';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart';
import 'package:speech_to_text/speech_to_text.dart';
import 'package:speech_to_text/speech_to_text_provider.dart';

import '../manager/dio_manager.dart';

class ChatPage extends StatefulWidget {
  final String rolePrompt;
  final String roleName;
  final String roleTips;
  final int type;
  final SpeechToText speech;

  final SpeechToTextProvider speechProvider;

  const ChatPage(
      {super.key,
      required this.rolePrompt,
      required this.roleName,
      required this.roleTips,
      required this.type,
      required this.speech,
      required this.speechProvider});

  @override
  State<StatefulWidget> createState() {
    return ChatState(
        rolePrompt: rolePrompt,
        roleName: roleName,
        roleTips: roleTips,
        type: type);
  }
}

class ChatState extends State<ChatPage> {
  List<Question> questionList = [];
  final TextEditingController _textEditingController = TextEditingController();
  var focusNode = FocusNode();
  final ScrollController _controller = ScrollController();
  late StreamSubscription<bool> keyboardSubscription;
  bool isLoading = false;
  final String rolePrompt;
  final String roleName;
  final String roleTips;
  final int type;
  bool showVoice = false;

  FlutterTts flutterTts = FlutterTts();

  ChatState({
    required this.rolePrompt,
    required this.roleName,
    required this.roleTips,
    required this.type,
  });

  late StreamSubscription eventSubscription;

  // final SpeechToText speech = SpeechToText();
  // late SpeechToTextProvider speechProvider;

  @override
  void initState() {
    super.initState();
    //
    _textEditingController.addListener(() {
      debugPrint(_textEditingController.text);
    });

    eventSubscription =
        EventManager.instance.eventBus.on<SwitchRoleEvent>().listen((event) {
      debugPrint("SwitchRoleEvent");
      if (mounted) {
        Future.delayed(const Duration(milliseconds: 500), () {
          setState(() {
            debugPrint("SwitchRoleEvent!!!：${StoreManager.getHomeRoleTips()}");
            if (questionList.isNotEmpty) {
              questionList[0].answer = StoreManager.getHomeRoleTips();
            } else {
              questionList.add(
                  Question(null, StoreManager.getHomeRoleTips(), false, false));
            }
          });
        });
      }
    });

    questionList.add(Question(null, roleTips, false, false));
    var keyboardVisibilityController = KeyboardVisibilityController();
    // Query
    debugPrint(
        'Keyboard visibility direct query: ${keyboardVisibilityController.isVisible}');

    // Subscribe
    keyboardSubscription =
        keyboardVisibilityController.onChange.listen((bool visible) {
      debugPrint('Keyboard visibility update. Is visible: $visible');
      if (visible) {
        scrollBottom();
      }
      StoreManager.setKeyboardVisible(visible);
    });

    _initSpeech();
    FlutterNativeSplash.remove();
    // _textEditingController.text = "我是一名互联网从业者，男，今年30岁，帮我规划下未来5年的人生规划。";
  }

  void _initSpeech() async {
    // speechProvider = SpeechToTextProvider(speech);
    // await speechProvider.initialize();
    ///tts
    await flutterTts.setSharedInstance(true);
    await flutterTts.setSpeechRate(0.55);

    await flutterTts.setVolume(0.5);

    await flutterTts.setPitch(1.0);

    await flutterTts.setIosAudioCategory(
        IosTextToSpeechAudioCategory.playback,
        [
          IosTextToSpeechAudioCategoryOptions.allowBluetooth,
          IosTextToSpeechAudioCategoryOptions.allowBluetoothA2DP,
          IosTextToSpeechAudioCategoryOptions.mixWithOthers
        ],
        IosTextToSpeechAudioMode.voicePrompt);

    await flutterTts.awaitSpeakCompletion(true);
  }



  @override
  void dispose() {
    keyboardSubscription.cancel();
    eventSubscription.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    double width = MediaQuery.of(context).size.width;
    debugPrint("build");
    return Scaffold(
      resizeToAvoidBottomInset: true,
      backgroundColor: ChatColors.lightColor,
      appBar: CustomAppbar(
        type: type,
        title: roleName,
        speech: widget.speech,
        speechProvider: widget.speechProvider,
      ),
      body: GestureDetector(
        onTap: () {
          focusNode.unfocus();
        },
        child: Column(
          children: [
            Expanded(
                child: ListView.builder(
                    itemCount: questionList.length,
                    controller: _controller,
                    itemBuilder: (BuildContext context, int index) {
                      return QuestionView(
                        question: questionList[index],
                        rolePrompt: rolePrompt,
                        scrollController: _controller,
                        questionStateCallBack: (isLoading) {
                          if (!isLoading) {
                            Future.delayed(const Duration(milliseconds: 500),
                                () {
                              this.isLoading = isLoading;
                              if (mounted) {
                                setState(() {});
                              }
                            });
                          }
                          debugPrint("isLoading=$isLoading");
                        },
                        focusNode: focusNode,
                        tts: flutterTts,
                      );
                    })),
            Stack(
              alignment: AlignmentDirectional.center,
              children: [
                Container(
                  alignment: Alignment.center,
                  padding: const EdgeInsets.only(right: 52, left: 32),
                  margin: EdgeInsets.fromLTRB(
                      12,
                      6,
                      12,
                      type == -1
                          ? 2
                          : MediaQuery.of(context).padding.bottom + 2),
                  height: 46,
                  width: width - 24,
                  decoration: BoxDecoration(
                    // color: ChatColors.commonLightColor,
                    color: ChatColors.darkTestColor,
                    borderRadius: const BorderRadius.all(Radius.circular(12.0)),
                  ),
                  child: TextField(
                    controller: _textEditingController,
                    style: const TextStyle(color: Colors.black),
                    keyboardType: TextInputType.text,
                    focusNode: focusNode,
                    maxLines: 2,
                    onChanged: (result) {
                      setState(() {
                        //更新发送按钮颜色
                      });
                    },
                    onSubmitted: (text) {
                      send(_textEditingController.text.trim());
                    },
                    textInputAction:
                        isLoading ? TextInputAction.done : TextInputAction.send,
                    // textAlignVertical: TextAlignVertical.center,
                    decoration: const InputDecoration(
                        contentPadding: EdgeInsets.fromLTRB(10, 8, 10, 0),
                        border: InputBorder.none,
                        hintText: '向AI提问',
                        hintStyle:
                            TextStyle(color: Color(0xFF707179), fontSize: 15)),
                  ),
                ),
                Positioned(
                    right: 24.0,
                    bottom: type == -1
                        ? 7
                        : MediaQuery.of(context).padding.bottom + 7,
                    child: isLoading
                        ? InkWell(
                            onTap: () {
                              EventManager.instance.eventBus
                                  .fire(StopAnswerEvent());
                            },
                            child: SizedBox(
                              width: 33,
                              height: 33,
                              child: Icon(Icons.stop_circle_outlined,
                                  size: 33, color: ChatColors.primaryColor),
                            ),
                          )
                        : InkWell(
                            //单击事件响应
                            onTap: () {
                              // setState
                              send(_textEditingController.text.trim());
                            },
                            child: _textEditingController.text.isEmpty
                                ? Container()
                                : Container(
                                    width: 32,
                                    height: 32,
                                    alignment: Alignment.center,
                                    decoration: BoxDecoration(
                                      color: ChatColors.primaryColor,
                                      borderRadius: const BorderRadius.all(
                                          Radius.circular(16.0)),
                                    ),
                                    child: const Icon(
                                      Icons.send,
                                      color: Colors.white,
                                      size: 20,
                                    ),
                                  ))),
                Positioned(
                    left: 8,
                    bottom: type == -1
                        ? 2.5
                        : MediaQuery.of(context).padding.bottom + 2.5,
                    child: IconButton(
                        onPressed: () {
                          // setState(() {
                          //   showVoice = !showVoice;
                          // });
                          showModalBottomSheet(
                            context: context,
                            isDismissible: false,
                            isScrollControlled: true,
                            backgroundColor: Colors.white,
                            builder: (context) {
                              return ProviderDemoApp(
                                speech: widget.speech,
                                speechProvider: widget.speechProvider,
                                speechToTextCallBack: (String value) {
                                  send(value);
                                },
                              );
                            },
                          );
                        },
                        icon: Icon(
                          Icons.graphic_eq_rounded,
                          color: ChatColors.primaryColor,
                          size: 30,
                        ))),
              ],
            )
          ],
        ),
      ),
    );
  }

  void send(String questionString) {
    if (questionString.isNotEmpty) {
      for (Question question in questionList) {
        question.isLastQuestion = false;
      }
      questionList.add(Question(questionString, null, false, true));
      isLoading = true;
      _textEditingController.text = "";
      FocusScope.of(context).unfocus(); //隐藏软键盘
      scrollBottom();
    }
  }

  void scrollBottom() {
    debugPrint("scroll bottom");
    Future.delayed(const Duration(milliseconds: 500), () {
      _controller.animateTo(
        _controller.position.maxScrollExtent,
        duration: const Duration(milliseconds: 500),
        curve: Curves.easeIn,
      );
    });
  }
}

class QuestionView extends StatefulWidget {
  final Question question;
  final ScrollController scrollController;
  final QuestionStateCallBack questionStateCallBack;
  final String rolePrompt;
  final FocusNode focusNode;
  final FlutterTts tts;

  const QuestionView(
      {super.key,
      required this.question,
      required this.rolePrompt,
      required this.scrollController,
      required this.questionStateCallBack,
      required this.focusNode,
      required this.tts});

  @override
  State<StatefulWidget> createState() {
    return QuestionState(
        question: question,
        rolePrompt: rolePrompt,
        scrollController: scrollController,
        questionStateCallBack: questionStateCallBack);
  }
}

class QuestionState extends State<QuestionView> {
  StreamController<SSEModel>? streamController;
  StreamTransformer<Uint8List, List<int>> unit8Transformer =
      StreamTransformer.fromHandlers(
    handleData: (data, sink) {
      sink.add(List<int>.from(data));
    },
  );
  final Question question;
  final ScrollController scrollController;
  final QuestionStateCallBack questionStateCallBack;
  final String continuePrompt = "继续";
  final String rolePrompt;
  bool isPlaying = false;
  late StreamSubscription eventSubscription;

  QuestionState(
      {required this.question,
      required this.rolePrompt,
      required this.scrollController,
      required this.questionStateCallBack});

  @override
  void initState() {
    super.initState();
    if (question.answer == null && question.prompt != null) {
      startSSE(question.prompt!);
    }
    eventSubscription =
        EventManager.instance.eventBus.on<StopAnswerEvent>().listen((event) {
      if (mounted) {
        setState(() {
          question.answer ??= "已停止回答。";
          stopSSE();
        });
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        question.prompt == null
            ? Container()
            : Container(
                padding: const EdgeInsets.fromLTRB(16, 24, 16, 0),
                width: MediaQuery.of(context).size.width,
                child: Row(
                  children: [
                    Expanded(child: Container()),
                    Container(
                      constraints: BoxConstraints(
                          minWidth: 24,
                          maxWidth: MediaQuery.of(context).size.width * 4 / 5),
                      padding: const EdgeInsets.fromLTRB(12, 12, 12, 12),
                      decoration: BoxDecoration(
                        borderRadius: const BorderRadius.only(
                            topLeft: Radius.circular(16),
                            topRight: Radius.circular(16),
                            bottomLeft: Radius.circular(16)),
                        color: ChatColors.primaryColor,
                      ),
                      child: Text(
                        question.prompt!,
                        style:
                            const TextStyle(color: Colors.white, fontSize: 16),
                        textDirection: TextDirection.ltr,
                        softWrap: true,
                      ),
                    )
                  ],
                ),
              ),
        Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            InkWell(
              highlightColor: Colors.transparent,
              // 透明色
              splashColor: Colors.transparent,
              // 透明色
              onTap: () {
                if (!StoreManager.isKeyboardVisible()) {
                  _showDialog(context, () {
                    //copy
                    Clipboard.setData(ClipboardData(text: question.answer!));
                    Utils.showToast("复制成功");
                  }, () {
                    //继续
                    if (question.prompt != null) {
                      startSSE(getLanContinue(question.prompt!));
                    } else {
                      startSSE(continuePrompt);
                    }
                  }, () {
                    reStartSSE();
                  }, () {
                    setState(() {});
                  });
                } else {
                  widget.focusNode.unfocus();
                }
              },
              onLongPress: () {
                if (!StoreManager.isKeyboardVisible()) {
                  _showDialog(context, () {
                    //copy
                    Clipboard.setData(ClipboardData(text: question.answer!));
                    Utils.showToast("复制成功");
                  }, () {
                    //继续
                    startSSE(continuePrompt);
                  }, () {
                    reStartSSE();
                  }, () {
                    setState(() {});
                  });
                } else {
                  widget.focusNode.unfocus();
                }
              },
              child: Container(
                alignment: Alignment.topLeft,
                padding: const EdgeInsets.fromLTRB(16, 12, 16, 3),
                width: MediaQuery.of(context).size.width,
                // color: ChatColors.commonLightColor,
                // color: ChatColors.commonTestLightColor,
                child: Row(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    question.answer == null
                        ? SizedBox(
                            width: 30,
                            height: 24,
                            child: SpinKitThreeBounce(
                              color: ChatColors.primaryColor,
                              size: 20.0,
                            ),
                          )
                        : Container(
                            constraints: BoxConstraints(
                                minWidth: 24,
                                maxWidth:
                                    MediaQuery.of(context).size.width * 4 / 5),
                            padding: const EdgeInsets.fromLTRB(12, 12, 12, 12),
                            decoration: BoxDecoration(
                              borderRadius: const BorderRadius.only(
                                  bottomLeft: Radius.circular(16),
                                  topRight: Radius.circular(16),
                                  bottomRight: Radius.circular(16)),
                              color: ChatColors.darkColor,
                            ),
                            child: Text(
                              question.answer!,
                              textAlign: TextAlign.start,
                              style: TextStyle(
                                  color: ChatColors.darkTextColor,
                                  fontSize: 16),
                              textDirection: TextDirection.ltr,
                              softWrap: true,
                            ),
                          ),
                    Expanded(child: Container())
                  ],
                ),
              ),
            ),
            (question.isLastQuestion && question.answer != null)
                ? Container(
              margin: EdgeInsets.only(left: 16),
                    padding: const EdgeInsets.only(left: 6,right: 6),
                    width: 72,
                    height: 26,
                    decoration: BoxDecoration(
                      borderRadius: const BorderRadius.all(
                          Radius.circular(16)),
                      color: ChatColors.darkColor,
                    ),
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.spaceAround,
                      crossAxisAlignment: CrossAxisAlignment.center,
                      children: [
                        InkWell(
                          highlightColor: Colors.transparent, // 透明色
                          splashColor: Colors.transparent, // 透明色
                          onTap: () {
                            Clipboard.setData(ClipboardData(text: question.answer!));
                            Utils.showToast("复制成功");
                          },
                          child: const Icon(
                            Icons.copy,
                            color: Colors.black,
                            size: 14,
                          ),
                        ),

                        InkWell(
                          highlightColor: Colors.transparent, // 透明色
                          splashColor: Colors.transparent, // 透明色
                          onTap: () {
                            _showDialog(context, () {
                              //copy
                              Clipboard.setData(ClipboardData(text: question.answer!));
                              Utils.showToast("复制成功");
                            }, () {
                              //继续
                              startSSE(continuePrompt);
                            }, () {
                              reStartSSE();
                            }, () {
                              setState(() {});
                            });
                          },
                          child: const Icon(
                            Icons.more_horiz,
                            color: Colors.black,
                            size: 14,
                          ),
                        ),
                        // Container(
                        //   width: 12,
                        // ),
                        // InkWell(
                        //   highlightColor: Colors.transparent, // 透明色
                        //   splashColor: Colors.transparent, // 透明色
                        //   onTap: () {
                        //     reStartSSE();
                        //   },
                        //   child: Container(
                        //     width: 80,
                        //     height: 24,
                        //     padding: const EdgeInsets.all(2.0),
                        //     margin: const EdgeInsets.only(top: 6),
                        //     decoration: BoxDecoration(
                        //       border: Border.all(
                        //           color: ChatColors.commonLightColor
                        //               .withOpacity(0.9),
                        //           width: 1),
                        //       borderRadius:
                        //           const BorderRadius.all(Radius.circular(4.0)),
                        //     ),
                        //     child: Row(
                        //       crossAxisAlignment: CrossAxisAlignment.center,
                        //       mainAxisAlignment: MainAxisAlignment.center,
                        //       children: [
                        //         question.isLoading
                        //             ? CupertinoActivityIndicator(
                        //                 radius: 6.0, color: Colors.white)
                        //             : Icon(
                        //                 Icons.sync,
                        //                 color: Colors.grey.withOpacity(0.9),
                        //                 size: 14,
                        //               ),
                        //         Padding(
                        //           padding: const EdgeInsets.only(left: 6),
                        //           child: Text(
                        //             question.isLoading ? "停止生成" : "重新生成",
                        //             style: TextStyle(
                        //                 color: Colors.grey.withOpacity(0.9),
                        //                 fontSize: 10,
                        //                 fontWeight: FontWeight.w700),
                        //           ),
                        //         )
                        //       ],
                        //     ),
                        //   ),
                        // ),
                        // Container(
                        //   width: 12,
                        // ),
                        // !question.isLoading
                        //     ? InkWell(
                        //         highlightColor: Colors.transparent, // 透明色
                        //         splashColor: Colors.transparent, // 透明色
                        //         onTap: () {
                        //           if (question.isLoading) {
                        //             stopSSE();
                        //           } else {
                        //             startSSE(continuePrompt);
                        //           }
                        //           setState(() {});
                        //         },
                        //         child: Container(
                        //           width: 64,
                        //           height: 24,
                        //           padding: const EdgeInsets.all(2.0),
                        //           margin: const EdgeInsets.only(top: 6),
                        //           decoration: BoxDecoration(
                        //             border: Border.all(
                        //                 color: ChatColors.commonLightColor
                        //                     .withOpacity(0.9),
                        //                 width: 1),
                        //             borderRadius: const BorderRadius.all(
                        //                 Radius.circular(4.0)),
                        //           ),
                        //           child: Row(
                        //             crossAxisAlignment:
                        //                 CrossAxisAlignment.center,
                        //             mainAxisAlignment: MainAxisAlignment.center,
                        //             children: [
                        //               Icon(
                        //                 Icons.play_circle_outline,
                        //                 color: Colors.grey.withOpacity(0.9),
                        //                 size: 14,
                        //               ),
                        //               Padding(
                        //                 padding: const EdgeInsets.only(left: 6),
                        //                 child: Text(
                        //                   question.isLoading ? "停止" : "继续",
                        //                   style: TextStyle(
                        //                       color:
                        //                           Colors.grey.withOpacity(0.9),
                        //                       fontSize: 10,
                        //                       fontWeight: FontWeight.w700),
                        //                 ),
                        //               )
                        //             ],
                        //           ),
                        //         ),
                        //       )
                        //     : Container(),
                      ],
                    ),
                  )
                : Container()
          ],
        )
      ],
    );
  }

  void playAnswer() {
    if (question.answer != null && question.answer!.isNotEmpty) {
      if (isPlaying) {
        widget.tts.stop();
        if (mounted) {
          setState(() {
            isPlaying = false;
          });
        }
      } else {
        if (mounted) {
          setState(() {
            isPlaying = true;
          });
        }

        widget.tts.setLanguage(getLan(question.answer!));
        widget.tts.speak(question.answer!);
        widget.tts.setCompletionHandler(() {
          if (mounted) {
            setState(() {
              isPlaying = false;
            });
          }
        });
      }
    }
  }

  void reStartSSE() {
    if (question.isLoading) {
      setState(() {
        question.isLoading = false;
        question.answer ??= "已停止回答。";
        stopSSE();
      });
    } else {
      startSSE(question.prompt!);
    }
  }

  void _showDialog(
      context,
      VoidCallback copyCallback,
      VoidCallback continueCallBack,
      VoidCallback refreshCallBack,
      VoidCallback switchSpeech) {
    showDialog(
      context: context,
      builder: (BuildContext context) {
        return AlertDialog(
          content: SizedBox(
            height: 172.0,
            child: Column(
              mainAxisAlignment: MainAxisAlignment.spaceAround,
              children: <Widget>[
                InkWell(
                  highlightColor: Colors.transparent, // 透明色
                  splashColor: Colors.transparent, // 透明色
                  onTap: () {
                    copyCallback();
                    Navigator.pop(context);
                  },
                  child: const Row(
                    children: <Widget>[
                      Icon(
                        Icons.copy,
                        size: 24,
                      ),
                      Padding(
                        padding: EdgeInsets.only(left: 12.0),
                        child: Text(
                          '复制',
                          style: TextStyle(color: Colors.black, fontSize: 15),
                        ),
                      ),
                    ],
                  ),
                ),
                const SizedBox(
                  height: 20.0,
                ),
                InkWell(
                    highlightColor: Colors.transparent, // 透明色
                    splashColor: Colors.transparent, // 透明色
                    onTap: () {
                      if (question.prompt != null) {
                        continueCallBack();
                      }
                      Navigator.pop(context);
                    },
                    child: const Row(
                      children: <Widget>[
                        Icon(
                          Icons.play_circle_outline,
                          size: 24,
                        ),
                        Padding(
                          padding: EdgeInsets.only(left: 12.0),
                          child: Text('继续',
                              style:
                                  TextStyle(color: Colors.black, fontSize: 15)),
                        ),
                      ],
                    )),
                const SizedBox(
                  height: 20.0,
                ),
                InkWell(
                    highlightColor: Colors.transparent, // 透明色
                    splashColor: Colors.transparent, // 透明色
                    onTap: () {
                      if (question.prompt != null) {
                        refreshCallBack();
                      }
                      Navigator.pop(context);
                    },
                    child: const Row(
                      children: <Widget>[
                        Icon(
                          Icons.sync,
                          size: 26,
                        ),
                        Padding(
                          padding: EdgeInsets.only(left: 12.0),
                          child: Text('重新生成',
                              style:
                                  TextStyle(color: Colors.black, fontSize: 15)),
                        ),
                      ],
                    )),
                const SizedBox(
                  height: 20.0,
                ),
                InkWell(
                    highlightColor: Colors.transparent, // 透明色
                    splashColor: Colors.transparent, // 透明色
                    onTap: () {
                      StoreManager.setSpeechAllowed(
                          !StoreManager.isSpeechAllowed());
                      switchSpeech();
                      Navigator.pop(context);
                    },
                    child: Row(
                      children: <Widget>[
                        const Icon(
                          Icons.mic_off,
                          size: 26,
                        ),
                        Padding(
                          padding: const EdgeInsets.only(left: 12.0),
                          child: Text(
                              StoreManager.isSpeechAllowed()
                                  ? '关闭语音跟读'
                                  : "开启语音跟读",
                              style: const TextStyle(
                                  color: Colors.black, fontSize: 15)),
                        ),
                      ],
                    )),
              ],
            ),
          ),
        );
      },
    );
  }

  void stopSSE() {
    streamController?.close();
    question.isLoading = false;
  }

  void startSSE(String prompt) async {
    if (!question.isLoading) {
      if (prompt != continuePrompt) {
        if (question.answer != null && question.answer!.isNotEmpty) {
          question.answer = null; //处理重新生成
        }
      }
      String speechText = "";
      debugPrint("startSSE");
      int msgIndex = 0;
      questionStateCallBack(true);
      question.isLoading = true;
      if (StoreManager.isSpeechAllowed()) {
        isPlaying = true;
      }
      try {
        Response response = await DioManager.instance.dio
            .get("chatgpt/chat/sseV2?prompt=$prompt&rolePrompt=$rolePrompt");
        var lineRegex = RegExp(r'^([^:]*)(?::)?(?: )?(.*)?$');
        var currentSSEModel = SSEModel(data: '', id: '', event: '');
        // ignore: close_sinks
        streamController = StreamController();

        response.data?.stream
            .transform(unit8Transformer)
            .transform(const Utf8Decoder())
            .transform(const LineSplitter())
            .listen(
          (dataLine) {
            if (dataLine.isEmpty) {
              ///This means that the complete event set has been read.
              ///We then add the event to the stream
              streamController?.add(currentSSEModel);
              currentSSEModel = SSEModel(data: '', id: '', event: '');
              return;
            }

            ///Get the match of each line through the regex
            Match match = lineRegex.firstMatch(dataLine)!;
            var field = match.group(1);
            if (field!.isEmpty) {
              debugPrint("换行？");
              return;
            }
            var value = '';
            if (field == 'data') {
              //If the field is data, we get the data through the substring
              value = dataLine.substring(
                5,
              );
            } else {
              value = match.group(2) ?? '';
            }
            switch (field) {
              case 'event':
                currentSSEModel.event = value;
                break;
              case 'data':
                currentSSEModel.data = (currentSSEModel.data ?? '') + value;

                break;
              case 'id':
                currentSSEModel.id = value;
                break;
              case 'retry':
                break;
            }
          },
          onError: (e, s) {
            debugPrint('---ERROR---');
            debugPrint(e);
            question.isLoading = false;
            questionStateCallBack(false);
            streamController?.addError(e, s);
          },
          onDone: () {
            if (question.answer != null) {
              if (question.answer!.contains(Utils.wxb)) {
                question.answer = Utils.wxb;
              }
            }
            question.isLoading = false;
            questionStateCallBack(false);
            debugPrint('Done!');
            scrollBottom();
            if (question.answer != null &&
                question.answer!.contains(Utils.haveNoTryCount)) {
              Future.delayed(const Duration(milliseconds: 1500), () {
                Navigator.push(context,
                    CupertinoPageRoute(builder: (BuildContext context) {
                  return VipPage(
                      "聊天-${StoreManager.getHomeRoleName()}-${question.prompt}");
                }));
              });
            }
          },
        );

        streamController?.stream.listen((event) {
          setState(() {
            String? msg = event.data;
            if (msg != null) {
              if (msg.isEmpty) {
                if (question.answer != null &&
                    !(question.answer!.endsWith("\n"))) {
                  msg = "\n";
                }
              }
              if (question.answer == null) {
                question.answer = msg;
                speechText = msg;
              } else {
                if (msg.contains(Utils.wxb)) {
                  question.answer = msg;
                } else {
                  if (question.answer == "已停止回答。") {
                    question.answer = "";
                  }
                  question.answer = "${question.answer}$msg";
                  speechText = "$speechText$msg";
                  msgIndex += 1;
                }
              }
              if (StoreManager.isSpeechAllowed()) {
                if (msgIndex <= 1) {
                  Future.delayed(const Duration(milliseconds: 500), () {
                    widget.tts.setLanguage(getLan(speechText));
                    widget.tts.speak(speechText);
                    speechText = "";
                    widget.tts.setCompletionHandler(() {
                      if (speechText.isNotEmpty) {
                        widget.tts.setLanguage(getLan(speechText));
                        widget.tts.speak(speechText);
                        speechText = "";
                      } else {
                        if (mounted) {
                          setState(() {
                            isPlaying = false;
                          });
                        }
                      }
                    });
                  });
                }
              }

              if (msgIndex % 20 == 0) {
                scrollBottom();
              }
            }
          });
        });
      } catch (e) {
        debugPrint('Error making request: $e');
      }
    }
  }

  String getLan(String string) {
    String lanc = 'zh-CN';

    final RegExp persian = RegExp('[\u0600-\u06FF]+');
    final RegExp english = RegExp('[a-zA-Z]+');
    final RegExp arabic = RegExp('[\u0621-\u064A]+');
    final RegExp chinese = RegExp('[\u4E00-\u9FFF]+');
    final RegExp japanese = RegExp('[\u3040-\u30FF]+');
    final RegExp korean = RegExp('[\uAC00-\uD7AF]+');
    final RegExp ukrainian = RegExp('[\u0400-\u04FF\u0500-\u052F]+');
    final RegExp russian = RegExp('[\u0400-\u04FF]+');
    final RegExp italian = RegExp('[\u00C0-\u017F]+');
    final RegExp french = RegExp('[\u00C0-\u017F]+');
    final RegExp spanish = RegExp(
        '[\u00C0-\u024F\u1E00-\u1EFF\u2C60-\u2C7F\uA720-\uA7FF\u1D00-\u1D7F]+');

    if (persian.hasMatch(string)) lanc = 'fa-IR';
    if (english.hasMatch(string)) lanc = 'en-US';
    if (arabic.hasMatch(string)) lanc = 'ar-SA';
    if (chinese.hasMatch(string)) lanc = 'zh-CN';
    if (japanese.hasMatch(string)) lanc = 'ja-JP';
    if (korean.hasMatch(string)) lanc = 'ko-KR';
    if (russian.hasMatch(string)) lanc = 'ru-RU';
    if (ukrainian.hasMatch(string)) lanc = 'uk-UA';
    if (italian.hasMatch(string)) lanc = 'it-IT';
    if (french.hasMatch(string)) lanc = 'fr-FR';
    if (spanish.hasMatch(string)) lanc = 'es-ES';

    return lanc;
  }

  String getLanContinue(String string) {
    String lanc = '继续';

    final RegExp persian = RegExp('[\u0600-\u06FF]+');
    final RegExp english = RegExp('[a-zA-Z]+');
    final RegExp arabic = RegExp('[\u0621-\u064A]+');
    final RegExp chinese = RegExp('[\u4E00-\u9FFF]+');
    final RegExp japanese = RegExp('[\u3040-\u30FF]+');
    final RegExp korean = RegExp('[\uAC00-\uD7AF]+');
    final RegExp ukrainian = RegExp('[\u0400-\u04FF\u0500-\u052F]+');
    final RegExp russian = RegExp('[\u0400-\u04FF]+');
    final RegExp italian = RegExp('[\u00C0-\u017F]+');
    final RegExp french = RegExp('[\u00C0-\u017F]+');
    final RegExp spanish = RegExp(
        '[\u00C0-\u024F\u1E00-\u1EFF\u2C60-\u2C7F\uA720-\uA7FF\u1D00-\u1D7F]+');

    if (persian.hasMatch(string)) lanc = "ادامه هید";
    if (english.hasMatch(string)) lanc = 'continue';
    if (arabic.hasMatch(string)) lanc = "يكمل";
    if (chinese.hasMatch(string)) lanc = '继续';
    if (japanese.hasMatch(string)) lanc = '続く';
    if (korean.hasMatch(string)) lanc = '계속하다';
    if (russian.hasMatch(string)) lanc = 'продолжать';
    if (ukrainian.hasMatch(string)) lanc = 'продовжувати';
    if (italian.hasMatch(string)) lanc = 'Continua';
    if (french.hasMatch(string)) lanc = 'continuer';
    if (spanish.hasMatch(string)) lanc = 'continuar';

    return lanc;
  }

  Map<String, String> voiceJixu = {
    "普通话": "继续",
    "英语": "continue",
    "法语": "continuer",
    "韩语": "계속하다",
    "日语": "続く",
    "意大利语": "Continua",
    "西班牙语": "continuar",
    "俄语": "продолжать",
    "乌克兰语": "продовжувати",
    "阿拉伯语": "يكمل",
    "波斯语": "ادامه هید"
  };

  void scrollBottom() {
    scrollController.animateTo(
      scrollController.position.maxScrollExtent,
      duration: const Duration(milliseconds: 500),
      curve: Curves.linear,
    );
  }

  @override
  void dispose() {
    super.dispose();
    stopSSE();
    eventSubscription.cancel();
  }
}

typedef QuestionStateCallBack = void Function(bool isLoading);

class CustomAppbar extends StatefulWidget implements PreferredSizeWidget {
  double contentHeight; //从外部指定高度

  int type;
  String title;
  final SpeechToText speech;

  final SpeechToTextProvider speechProvider;

  CustomAppbar(
      {super.key,
      this.contentHeight = 56,
      required this.type,
      required this.title,
      required this.speech,
      required this.speechProvider});

  @override
  State<StatefulWidget> createState() {
    return _CustomAppbarState();
  }

  @override
  Size get preferredSize => Size.fromHeight(contentHeight);
}

class _CustomAppbarState extends State<CustomAppbar> {
  late StreamSubscription eventSubscription;

  @override
  void initState() {
    super.initState();
    eventSubscription =
        EventManager.instance.eventBus.on<SwitchRoleEvent>().listen((event) {
      if (mounted) {
        Future.delayed(const Duration(milliseconds: 500), () {
          setState(() {});
        });
      }
    });
  }

  @override
  void dispose() {
    super.dispose();
    if (eventSubscription != null) {
      eventSubscription.cancel();
    }
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      color: ChatColors.lightColor,
      child: SafeArea(
        top: true,
        child: SizedBox(
            height: widget.contentHeight,
            child: Stack(
              alignment: Alignment.centerLeft,
              children: <Widget>[
                widget.type == -1
                    ? InkWell(
                        onTap: () {
                          Navigator.push(context, CupertinoPageRoute(
                              builder: (BuildContext context) {
                            return RoleTabPage(
                              isSelectRole: true,
                              speech: widget.speech,
                              speechProvider: widget.speechProvider,
                            );
                          }));
                        },
                        child: Row(
                          mainAxisAlignment: MainAxisAlignment.center,
                          children: [
                            Text(
                              StoreManager.getHomeRoleName(),
                              style: const TextStyle(
                                  color: Colors.black,
                                  fontSize: 16,
                                  fontWeight: FontWeight.w600),
                            ),
                            const Padding(
                              padding: EdgeInsets.only(left: 2.0),
                              child: Icon(Icons.swap_vert,
                                  size: 20, color: Colors.black),
                            )
                          ],
                        ),
                      )
                    : InkWell(
                        onTap: () {
                          Navigator.pop(context);
                        },
                        child: Row(
                          mainAxisAlignment: MainAxisAlignment.center,
                          children: [
                            const Padding(
                              padding: EdgeInsets.only(left: 12.0),
                              child: Icon(
                                Icons.arrow_back_ios,
                                color: Colors.black,
                                size: 20,
                              ),
                            ),
                            Expanded(child: Container()),
                            Text(
                              widget.title,
                              style: const TextStyle(
                                  color: Colors.black,
                                  fontSize: 15,
                                  fontWeight: FontWeight.w600),
                            ),
                            Expanded(child: Container()),
                          ],
                        ),
                      ),
              ],
            )),
      ),
    );
  }
}

typedef SpeechToTextCallBack = void Function(String value);
